package csel.view;

import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.*;
import java.io.File;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

/**
 * This is an abstract class that provides some common functionality, such as
 * processing GameCommands? and implementing observer structure, for all viewports. 
 * @author David
 */
public abstract class Viewport
{
	private final List<ActionListener> _actionListeners;
	private final List<KeyListener> _keyListeners;
	
	public Viewport()
	{
		_actionListeners = new LinkedList<ActionListener>();
		_keyListeners = new LinkedList<KeyListener>();
	}
	
	/**
	 * Set whether the viewport is displayed or not.
	 */
	public abstract void setVisible(boolean visibility);
	
	/**
	 * Deconstruct the Viewport so that it may be garbage collected.
	 */
	public abstract void close();
	
	protected abstract Container getContainer();

	/**
	 * Prompt the user with a YES/NO dialog.
	 * @param message message to display to user.
	 * @return true if they clicked YES.
	 */
	public boolean displayConfirm(String message)
	{
		int ret = JOptionPane.showConfirmDialog(getContainer(),
				message, "Are you for real?", JOptionPane.YES_NO_OPTION);
		
		return (ret == JOptionPane.YES_OPTION);
	}
	
	/**
	 * FileFilter class to restrict FileDialogs to .sav files.
	 * @author david
	 */
	private class SaveGameFileFilter extends FileFilter
	{

		@Override
		public boolean accept(File file)
		{
			return "sav".equals(getExtension(file));
		}

		@Override
		public String getDescription()
		{
			return "Save Game Files (*.sav)";
		}
		
	    /**
	     * Get the extension of a file.
	     * 
	     * Copied from Sun.
	     */ 
	    private String getExtension(File f)
	    {
	        String ext = null;
	        String s = f.getName();
	        int i = s.lastIndexOf('.');

	        if (i > 0 &&  i < s.length() - 1) {
	            ext = s.substring(i+1).toLowerCase();
	        }
	        return ext;
	    }

	}
	
	/**
	 * Utility method to make a JFileChooser just how we want it.
	 */
	private final JFileChooser makeFileChooser()
	{
		JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
		
		fc.setFileFilter(new SaveGameFileFilter());
		
		return fc;
	}
	
	/**
	 * Prompts the user with an OpenFile dialog.
	 * @return the filepath that the user chose, or <strong>null</strong> if canceled.
	 */
	public String promptOpenDialog()
	{
		JFileChooser fc;
		
		fc = makeFileChooser();
		
		if (fc.showOpenDialog(getContainer()) != JFileChooser.APPROVE_OPTION)
		{
			System.out.printf("[VIEW] User canceled open dialog.\n");
			return null;
		}
		
		return fc.getSelectedFile().getAbsolutePath();
	}

	/**
	 * Prompts the user with an SaveFile dialog.
	 * @return the filepath that the user chose, or <strong>null</strong> if canceled.
	 */
	public String promptSaveDialog()
	{
		JFileChooser fc;
		
		fc = makeFileChooser();
		
		if (fc.showSaveDialog(getContainer()) != JFileChooser.APPROVE_OPTION)
		{
			System.out.printf("[VIEW] User canceled save dialog.\n");
			return null;
		}

		return fc.getSelectedFile().getAbsolutePath();
	}
	
	/**
	 * Process a GameCommand.
	 */
	public void accept(csel.model.GameCommand command)
	{
		command.execute();
	}
	
	public void addActionListener(ActionListener l)
	{
		_actionListeners.add(l);
	}

	/**
	 * Remove the specified ActionListener from the internal collection.
	 * @return true if the ActionListener existed in the collection
	 */
	public boolean removeActionListener(ActionListener l)
	{
		return _actionListeners.remove(l);
	}
	
	public void addKeyboardListener(KeyListener l)
	{
		_keyListeners.add(l);
	}
	
	/**
	 * Remove the specified KeyListener from the internal collection.
	 * @return true if the KeyListener existed in the collection
	 */
	public boolean removeKeyListener(KeyListener l)
	{
		return _keyListeners.remove(l);
	}
	
	protected class TrampolineListener implements ActionListener, KeyListener
	{

		public void actionPerformed(ActionEvent event)
		{
			for (ActionListener l : _actionListeners)
				l.actionPerformed(event);
		}

		public void keyPressed(KeyEvent event)
		{
			System.out.printf("[VIEW] A viewport got a key press: %s\n", event);
			for (KeyListener l : _keyListeners)
				l.keyPressed(event);
		}

		public void keyReleased(KeyEvent event)
		{
			for (KeyListener l : _keyListeners)
				l.keyReleased(event);
		}

		public void keyTyped(KeyEvent event)
		{
			for (KeyListener l : _keyListeners)
				l.keyTyped(event);
		}
		
	}

	public void paintComponent(Graphics g) {
		// TODO Auto-generated method stub
		
	}
}
